﻿using System;
using Selenium;

namespace Quail
{
    /// <summary>
    /// Wraps simple web events for a given control
    /// </summary>
    public class WebEvent
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="WebEvent"/> class.
        /// </summary>
        /// <param name="control">The control.</param>
        public WebEvent(WebControl control)
        {
            Control = control;
        }

        /// <summary>
        /// Gets the control for the event
        /// </summary>
        public WebControl Control
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the Selenium interface
        /// </summary>
        protected ISelenium SeleniumInterface
        {
            get { return Control.Browser.SeleniumInterface; }
        }

        /// <summary>
        /// Clicks a control
        /// </summary>
        public void Click()
        {
            var task = Control.BeginTask("Click");
            try
            {
                /*
                var tag = Control.Tag;
                KnownAttribute attrTag = KnownAttribute.ID;
                string atname = null, atvalue = null;

                switch (tag)
                {
                    case "A":
                        attrTag = KnownAttribute.Href;
                        break;
                    case "IMG":
                        attrTag = KnownAttribute.OnClick;
                }

                if (attrTag != KnownAttribute.ID)
                {
                    var at = Control.Attr(attrTag);
                    if (!string.IsNullOrEmpty(at))
                        task.AddAttribute(KnownAttributeToString(attrTag), at);
                }
                */
                SeleniumInterface.Click(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the click event at a specific coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void ClickAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("ClickAt", coord);
            try
            {
                SeleniumInterface.ClickAt(Control.Locator, coord);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the focus event
        /// </summary>
        public void Focus()
        {
            var task = Control.BeginTask("Focus");
            try
            {
                SeleniumInterface.Focus(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the blur (lose focus) event
        /// </summary>
        public void Blur()
        {
            FireEvent("blur");
        }

        /// <summary>
        /// Performs the mouseover event
        /// </summary>
        public void MouseOver()
        {
            var task = Control.BeginTask("MouseOver");
            try
            {
                SeleniumInterface.MouseOver(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouseout event
        /// </summary>
        public void MouseOut()
        {
            var task = Control.BeginTask("MouseOut");
            try
            {
                SeleniumInterface.MouseOut(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouse down event
        /// </summary>
        public void MouseDown()
        {
            var task = Control.BeginTask("MouseDown");
            try
            {
                SeleniumInterface.MouseDown(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouse down event at a specific coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MouseDownAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("MouseDownAt", coord);
            try
            {
                SeleniumInterface.MouseDownAt(Control.Locator, coord);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouse up event at a specific coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MouseUpAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("MouseUpAt", coord);
            try
            {
                SeleniumInterface.MouseUpAt(Control.Locator, coord);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouse right-button down event over the control
        /// </summary>
        public void MouseDownRight()
        {
            var task = Control.BeginTask("MouseDownRight");
            try
            {
                SeleniumInterface.MouseDownRight(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }
        
        /// <summary>
        /// Performs the mouse right-button down event at a specific coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MouseDownRightAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("MouseDownRightAt", coord);
            try
            {
                SeleniumInterface.MouseDownRightAt(Control.Locator, string.Format("{0},{1}", x, y));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mouse right-button up event at a specific coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MouseUpRightAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("MouseUpRightAt", coord);
            try
            {
                SeleniumInterface.MouseUpRightAt(Control.Locator, string.Format("{0},{1}", x, y));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mousemove event over the control
        /// </summary>
        public void MouseMove()
        {
            var task = Control.BeginTask("MouseMove");
            try
            {
                SeleniumInterface.MouseMove(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the mousemove event at a specific x/y coordinate
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MouseMoveAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("MouseMoveAt", coord);
            try
            {
                SeleniumInterface.MouseMoveAt(Control.Locator, string.Format("{0},{1}", x, y));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the keypress event
        /// </summary>
        /// <param name="c"></param>
        public void KeyPress(char c)
        {
            var task = Control.BeginTask("KeyPress", c.ToString());
            try
            {
                SeleniumInterface.KeyPress(Control.Locator, c.ToString());
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs the key press event
        /// </summary>
        /// <param name="keyCode"></param>
        public void KeyPress(int keyCode)
        {
            var task = Control.BeginTask("KeyPress", keyCode.ToString());
            try
            {
                SeleniumInterface.KeyPress(Control.Locator, string.Format("\\{0}", keyCode));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs keydown event
        /// </summary>
        /// <param name="c"></param>
        public void KeyDown(char c)
        {
            var task = Control.BeginTask("KeyDown", c.ToString());
            try
            {
                SeleniumInterface.KeyDown(Control.Locator, c.ToString());
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs keydown event
        /// </summary>
        /// <param name="keyCode"></param>
        public void KeyDown(int keyCode)
        {
            var task = Control.BeginTask("KeyDown", keyCode.ToString());
            try
            {
                SeleniumInterface.KeyDown(Control.Locator, string.Format("\\{0}", keyCode));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// performs Keyup event
        /// </summary>
        /// <param name="c"></param>
        public void KeyUp(char c)
        {
            var task = Control.BeginTask("KeyUp", c.ToString());
            try
            {
                SeleniumInterface.KeyUp(Control.Locator, c.ToString());
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs keyup event
        /// </summary>
        /// <param name="keyCode"></param>
        public void KeyUp(int keyCode)
        {
            var task = Control.BeginTask("KeyUp", keyCode.ToString());
            try
            {
                SeleniumInterface.KeyUp(Control.Locator, string.Format("\\{0}", keyCode));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs mouse double-click event
        /// </summary>
        public void DoubleClick()
        {
            var task = Control.BeginTask("DoubleClick");
            try
            {
                SeleniumInterface.DoubleClick(Control.Locator);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Performs mouse double-click event at specific coordinates
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void DoubleClickAt(int x, int y)
        {
            var coord = CoordToString(x, y);
            var task = Control.BeginTask("DoubleClickAt", coord);
            try
            {
                SeleniumInterface.DoubleClickAt(Control.Locator, string.Format("{0},{1}", x, y));
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// Fires a specific event on the control
        /// </summary>
        /// <param name="eventName"></param>
        public void FireEvent(string eventName)
        {
            var task = Control.BeginTask("FireEvent", eventName);
            try
            {
                SeleniumInterface.FireEvent(Control.Locator, eventName);
                task.Finish();
            }
            catch (Exception e)
            {
                task.Finish(e);
                throw;
            }
        }

        /// <summary>
        /// converts two integers to coordinates needed in selenium
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        protected static string CoordToString(int x, int y)
        {
            return string.Format("{0},{1}", x, y);
        }
    }
}
